#ifndef __TOY__TEXTURE__H__
#define __TOY__TEXTURE__H__

#include "ToyBmp.h"
#include "ToyMath.h"
#include "ToyMath.h"

namespace ToyCube {

enum class Tex_Interplate{
    /** 临近*/
    Nearest,
    /** 线性*/
    Bilinear,
    /** 立方*/
    Bicubic
};

class ToyTexture : public Bitmap{
    
public:
    ToyTexture(int width, int height, Tex_Interplate interpolate = Tex_Interplate::Bilinear) : Bitmap(width, height),
                                                                 _interpolate(interpolate){
        
    }
    
    ToyTexture(const char *filename) : Bitmap(filename),
                                       _interpolate(Tex_Interplate::Bilinear){
        
    }
    
    virtual ~ToyTexture(){}
    
    Vec<4, float> Sample2D(float u, float v){
        //bmp颜色 高->低 argb
        uint32_t color = 0;
        if(_interpolate == Tex_Interplate::Bilinear){
            color = InterplateBilinear(u, v);
        }else{
            
        }
        Vec<4, float> vec;
        vec[3] = (0xff & (color >> 24)) / 255.0f;  //a
        vec[2] = (0xff & (color >> 16)) / 255.0f;  //r
        vec[1] = (0xff & (color >> 8)) / 255.0f;   //g
        vec[0] = (0xff & (color)) / 255.0f;        //b
        
        return vec;
    }
    
    inline uint32_t InterplateBilinear(float u, float v){
        
        uint32_t color = 0;
        
        float x = u * _w;
        float y = v * _h;
        
        int tmp_x = x+0.5;
        int tmp_y = y+0.5;
        
        int x0 = x;
        int y0 = y;
        //默认离左边 上边近
        int x1 = x0-1;
        int y1 = y0-1;
        //如果x进位 说明离右边近
        if(tmp_x > x0){
            x1 = tmp_x;
        }
        //如果y进位 说明离下边近
        if(tmp_y > y0){
            y1 = tmp_y;
        }
        x1 = Mid3(x1, 0, _w-1);
        //确保x0在左 x1在右
        if(x1 < x0){
            std::swap(x0, x1);
        }
        //确保y0在上 y1在下
        y1 = Mid3(y1, 0, _h-1);
        if(y1 < y0){
            std::swap(y0, y1);
        }
        //离这个点中心越近 占的比重越大，这里用1减这个距离
        float ku = 1-(x - (x0+0.5));
        float kv = 1-(y - (y0+0.5));
        
        uint32_t c00 = GetPixel(x0, y0);
        uint32_t c01 = GetPixel(x1, y0);
        uint32_t c10 = GetPixel(x0, y1);
        uint32_t c11 = GetPixel(x1, y1);
        //先合并左右 再合并上下
        uint32_t b = ((c00 & 0x000000ff) * ku + (c01 & 0x000000ff) * (1-ku))*kv + ((c10 & 0x000000ff) * ku + (c11 & 0x000000ff) * (1-ku))*(1-kv);
        uint32_t g = (((c00>>8) & 0x000000ff) * ku + ((c01>>8) & 0x000000ff) * (1-ku))*kv + (((c10>>8) & 0x000000ff) * ku + ((c11>>8) & 0x000000ff) * (1-ku))*(1-kv);
        uint32_t r = (((c00>>16) & 0x000000ff) * ku + ((c01>>16) & 0x000000ff) * (1-ku))*kv + (((c10>>16) & 0x000000ff) * ku + ((c11>>16) & 0x000000ff) * (1-ku))*(1-kv);
        
        if(b>255) b=255;
        if(g>255) g=255;
        if(r>255) r=255;
        
        return 0xff000000 | (r<<16) | (g<<8) | b;
        
        return color;
    }
    
    void SetName(std::string name){
        _name = name;
    }
    
protected:
    Tex_Interplate _interpolate;
    std::string _name;
};

}

#endif
